#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "iostream"
using namespace std;
/*
syn 与 tokenType 与 token 对应关系
0: comments
1: keywords: if, then, else, while
2: identifiers 
3: operators: + - / * = == < <= > >=
4: delimiters: ( ) { } ; ,
5: numbers
6: unknown
*/

static char tokenType[7][20] = {
    "comment", "keyword", "identifier", "operator", "delimiter", "number","unknown"
};

static char keywords[4][10] = {
    "if", "then", "else", "while"
};

// 处理comment
void filterResource(char r[], int index) {
    char tempString[10000];
    int count = 0;
    for(int i = 0; i < index; i++) {
        if(r[i] == '/' && i < index - 1 && r[i + 1] == '/') {
            while(i < index && r[i] != '\n') {
                i++;
            }
        }
        tempString[count++] = r[i];
    }
    tempString[count] = '\0';
    strcpy(r, tempString);
}

bool isLetter(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

bool isDigit(char c) {
    return c >= '0' && c <= '9';
}

bool isKeywords(char keywords[][10], char s[]) {
    for (int i = 0; i < 4; i++) {
       if(strcmp(keywords[i], s) == 0) {
            return true;
        }
    }
    return false;
}

void scanner(int &syn, char resourceProject[], char token[], int &index, int &colIndex, int &rowIndex, int &count) {
    rowIndex += count; 
    //count记录下当前词的长度，下次调用函数时，rowIndex即指向上个词后
    count = 0;
    char ch = resourceProject[index];
    if (isLetter(resourceProject[index])) {
        if (resourceProject[index] == 'E' || resourceProject[index] == 'e') {

        } else {

        }
        token[count++] = resourceProject[index];
        index++;
        while (isLetter(resourceProject[index]) || isDigit(resourceProject[index])) {
            token[count++] = resourceProject[index];
            index++;
        }
        token[count] = '\0';
        syn = isKeywords(keywords, token) ? 1 : 2;
    } else if(isDigit(resourceProject[index])) {
        while (isDigit(resourceProject[index])) {
            token[count++] = resourceProject[index];
            index++;
        }
        token[count] = '\0';
        syn = 5;
    } else if (ch == '+' || ch == '-' || ch == '/' || ch == '*') {
        token[0] = ch;
        index++;
        token[1] = '\0';
        syn = 3;
    } else if (ch == '=' || ch == '<' || ch == '>' ) {
        token[count++] = ch;
        index++;
        if(resourceProject[index] == '=') {
            token[count++] = resourceProject[index];
            index++;
        }
        token[count] = '\0';
        syn = 3;
    } else if(ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == ',' || ch == ';') {
        token[count++] = ch;
        index++;
        token[count] = '\0';
        syn = 4;
    } else if(ch == '\0') {
        syn = 0;
    } else {
        syn = 6;
        index++;
        rowIndex++;
        count = 0;
        if(ch == '\n') {
            colIndex++;
            rowIndex = 0;
        }
    }
    return;
}

int main() {
    //打开一个文件，读取其中的源程序
    char resourceProject[10000];
    char token[20] = { 0 };
    int syn = 6, i;
    //初始化
    int index = 0, colIndex = 0, rowIndex = 0, count = 0;

    //源程序指针
    FILE *fpr, *fpw;

    //打开输入文件
    if ((fpr = fopen("../input.txt", "r")) == NULL) {
        
        cout << "can't open this in file";
        exit(0);
    }
    resourceProject[index] = fgetc(fpr);
    
    //将源程序读入resourceProject[]数组
    while (resourceProject[index] != EOF) {
        index++;
        resourceProject[index] = fgetc(fpr);
    }

    //过滤注释
    filterResource(resourceProject, index);
    cout << "过滤注释结果：" << endl << resourceProject << endl;

    //打开输出文件
    if ((fpw = fopen("output/lexer_out.txt", "w+")) == NULL) {
        cout << "can't open this out file";
        exit(0);
    }

    index = 0;
    while(syn != 0) {
        //启动扫描
        scanner(syn, resourceProject, token, index, colIndex, rowIndex, count);
        if(syn != 0 && syn != 6)
            fprintf(fpw, "(%s , %s , %d , %d)\n", tokenType[syn], token, colIndex, rowIndex);
    }
}